package com.qdxwx.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.FileCopyUtils;

import javax.imageio.*;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.*;
import java.io.File;
import java.io.FileOutputStream;

/**
 * Qdx NetSchool Platform
 * @author qdxwx
 * @updateTime 2022/5/25
 * @description
 */
public class ImageUtils {

    private final static Logger logger = LoggerFactory.getLogger(ImageUtils.class);

    public static void main(String[] args) {
        //放大缩小图片
        //imageScaler("F:/image/4.png", "F:/image/ex/12.png", 70, false);//true放大  false缩小
        //裁剪图片
        //imageCut("e:/1.jpg", "e:/3.jpg", 100, 100, 500, 500);
        //格式转换
        //imageConvert("e:/1.jpg", "gif", "e:/4.jpg");
        //转换成黑白图片G
        //imageGray("e:/1.jpg", "e:/5.jpg");
        //添加水印文字
        //imagePress("我是水印文字", "e:/1.jpg", "e:/6.jpg", "宋体", Font.BOLD, Color.white, 50, 100, 100, 0.5f);
        //添加水印图片
        //imagePress("e:/添加水印.jpg", "e:/1.jpg", "e:/7.jpg", 0, 0, 0.5f);
        zoomWithCut("D:\\mmexport1624260341123.jpg","D:\\mmexport1624260341123-n.jpg", 500, 500);
        //System.out.println(getSuffix("asdfsdf.jsp"));;
    }

    /**
     * 图片放大缩小
     *
     * @param srcPath 源图片路径
     * @param newPath 处理后图片的路径
     * @param scale   倍数
     * @param flag    true放大  false缩小
     * @return true处理成功 false处理失败
     */
    public static boolean scaler(String srcPath, String newPath, int scale, boolean flag) {
        try {
            //得到原图片
            BufferedImage bufferedImage = ImageIO.read(new File(srcPath));
            //获取图片高宽
            int width = bufferedImage.getWidth();
            int height = bufferedImage.getHeight();
            float _scale = (float) scale / 100f;

            //判断是放大还是缩小，放大除以百分比，缩小乘以百分比
            if (flag) {//放大
                width = (int) ((float) width / _scale);
                height = (int) ((float) height / _scale);
            } else {//缩小
                width = (int) ((float) width * _scale);
                height = (int) ((float) height * _scale);
            }
            //得到缩放后台的图片
            /* width - 将图像缩放到的宽度。 height - 将图像缩放到的高度。 hints - 指示用于图像重新取样的算法类型的标志。  */
            Image image = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);

            //设置绘制新图片的缓冲对象
            BufferedImage outputImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics graphics = outputImage.getGraphics();
            graphics.drawImage(image, 0, 0, null);// 绘制处理后的图
            graphics.dispose();
            File file = new File(newPath);
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            //写出新的图片
            ImageIO.write(outputImage, getFileExt(newPath), file);
            //System.out.println("处理成功");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 修改图片大小
     *
     * @param srcPath   源图片路径
     * @param newPath   处理后图片的路径
     * @param newWidth  新的宽度
     * @param newHeight 新的高度
     * @return true处理成功 false处理失败
     */
    public static boolean changeSize(String srcPath, String newPath, int newWidth, int newHeight) {
        try {
            //得到原图片
            BufferedImage bufferedImage = ImageIO.read(new File(srcPath));
            /* width - 将图像缩放到的宽度。 height - 将图像缩放到的高度。 hints - 指示用于图像重新取样的算法类型的标志。  */
            Image image = bufferedImage.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);

            //设置绘制新图片的缓冲对象
            BufferedImage outputImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
            Graphics graphics = outputImage.getGraphics();
            graphics.drawImage(image, 0, 0, null);// 绘制处理后的图
            graphics.dispose();
            File file = new File(newPath);
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            //写出新的图片
            ImageIO.write(outputImage, getFileExt(newPath), file);
            //System.out.println("处理成功");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 图像裁剪
     *
     * @param srcPath 源图片路径
     * @param newPath 处理后图片路径
     * @param x       切片x坐标起点
     * @param y       切片y坐标起点
     * @param width   切片宽度
     * @param height  切片高度
     */
    public static boolean cut(String srcPath, String newPath, int x, int y, int width, int height) {
        try {
            Image img;
            ImageFilter cropFilter;
            // 读取源图像
            BufferedImage bi = ImageIO.read(new File(srcPath));
            int srcWidth = bi.getWidth();      // 源图宽度
            int srcHeight = bi.getHeight();    // 源图高度

            //若原图大小大于切片大小，则进行切割
            if (srcWidth > width || srcHeight > height) {
                Image image = bi.getScaledInstance(srcWidth, srcHeight, Image.SCALE_DEFAULT);

                int w1 = Math.min(width, srcWidth);
                int h1 = Math.min(height, srcHeight);

                cropFilter = new CropImageFilter(x, y, w1, h1);
                img = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(image.getSource(), cropFilter));
                BufferedImage tag = new BufferedImage(w1, h1, BufferedImage.TYPE_INT_RGB);
                Graphics g = tag.getGraphics();
                g.drawImage(img, 0, 0, null); // 绘制缩小后的图
                g.dispose();
                File file = new File(newPath);
                if (!file.getParentFile().exists()) {
                    file.getParentFile().mkdirs();
                }
                // 输出为文件
                ImageIO.write(tag, "JPG", file);
            }
            return true;
        } catch (Exception e) {
            logger.error("图片裁剪失败：" + e.getMessage());
            return false;
        }
    }

    public static void press(String srcPath, String newPath, String pressText, float alpha
            , String fontName, int fontSize, Color color, int areaX, int areaY) {
        try {
            BufferedImage src = ImageIO.read(new File(srcPath));
        }
        catch (Exception ex){
            logger.error(ex.getMessage());

        }
    }

    public static void press(BufferedImage srcImage, String newPath, String pressText, float alpha
            , String fontName, int fontSize, Color color, int areaX, int areaY) {
        try {

            int width = srcImage.getWidth();
            int height = srcImage.getHeight();
            if (width > 1024) {
                height = (int) ((1024.0 / width) * height);
                width = 1024;
            }
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = image.createGraphics();
            g.drawImage(srcImage, 0, 0, width, height, null);
            g.setColor(color);
            g.setFont(new Font(fontName, Font.ITALIC, fontSize));
            //g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
            // 在指定坐标绘制水印文字
            int x = 10;
            int y = 10;
            int width_wm = pressText.length() * fontSize;
            switch (areaX) {
                case 1: {
                    if (width > width_wm) {
                        x = (width - width_wm) / 2;
                    }
                    break;
                }
                case 2: {
                    if (width > width_wm) {
                        x = (width - width_wm) - 10;
                    }
                    break;
                }
            }
            switch (areaY) {
                case 1: {
                    if (height > fontSize) {
                        y = (height - fontSize) / 2;
                    }
                    break;
                }
                case 2: {
                    if (height > fontSize) {
                        y = (height - fontSize) - 10;
                    }
                    break;
                }
            }
            g.drawString(pressText, x, y);
            g.dispose();
            File file = new File(newPath);
            if (!file.getParentFile().exists()) {
                if (!file.getParentFile().mkdirs()) {
                    System.out.println("创建目录失败：" + file.getPath());
                }
            }
            ImageIO.write(image, getFileExt(newPath), file);// 输出到文件流
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 给图片添加图片水印
     *
     * @param srcPath  源图像地址
     * @param newPath  目标图像地址
     * @param srcWater 水印图片
     * @param alpha    透明度：alpha 必须是范围 [0.0, 1.0] 之内（包含边界值）的一个浮点数字
     */
    public static void press(String srcPath, String newPath, BufferedImage srcWater, float alpha) {
        press(new File(srcPath), newPath, srcWater, alpha);
    }

    public static void press(File srcFile, String newPath, BufferedImage srcWater, float alpha) {
        try {
            BufferedImage src = ImageIO.read(srcFile);
            press(src, newPath, srcWater, alpha);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void press(BufferedImage srcImage, String newPath, BufferedImage srcWater, float alpha) {
        try {
            int width = srcImage.getWidth();
            int height = srcImage.getHeight();
            if (width > 1024) {
                height = (int) ((1024.0 / width) * height);
                width = 1024;
            }
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = image.createGraphics();
            g.drawImage(srcImage, 0, 0, width, height, null);

            int width_wm = srcWater.getWidth();
            int height_wm = srcWater.getHeight();
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
            g.drawImage(srcWater, (width - width_wm) / 2, (height - height_wm) / 2, width_wm, height_wm, null);
            //g.rotate(Math.toRadians(0.3), 0, 0);
            // 水印文件结束
            g.dispose();
            File file = new File(newPath);
            if (!file.getParentFile().exists()) {
                if (!file.getParentFile().mkdirs()) {
                    System.out.println("创建目录失败：" + file.getPath());
                }
            }
            ImageIO.write(image, getFileExt(newPath), file);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 图像类型转换
     *
     * @param srcPath    源图片路径
     * @param newPath    处理后的图片路径
     * @param formatName 要转换的格式
     */
    public static void convert(String srcPath, String newPath, String formatName) {
        try {
            File f = new File(srcPath);
            BufferedImage src = ImageIO.read(f);
            ImageIO.write(src, formatName, new File(newPath));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 图片转换成黑白
     *
     * @param srcPath 原图片路径，全路径
     * @param newPath 新图片路径，全路径
     */
    public static void gray(String srcPath, String newPath) {
        try {
            BufferedImage src = ImageIO.read(new File(srcPath));
            ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
            ColorConvertOp op = new ColorConvertOp(cs, null);
            src = op.filter(src, null);
            ImageIO.write(src, getFileExt(newPath), new File(newPath));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
     * 图片缩放,w，h为缩放的目标宽度和高度
     * src为源文件路径
     */
    public static boolean zoom(String fullPath, int width, int height) {
        if (fullPath == null || fullPath.trim().length() == 0) {
            return false;
        }
        if (width <= 0 && height <= 0) {
            return false;
        }
        try {
            File srcFile = new File(fullPath);
            //得到原图片
            BufferedImage bufferedImage = ImageIO.read(srcFile);
            //获取图片高宽
            int srcWidth = bufferedImage.getWidth();
            int srcHeight = bufferedImage.getHeight();
            float _scale = 1;
            if (width > 0 && height <= 0) {
                _scale = (float) width / srcWidth;
                height = (int) (srcHeight * _scale);
            }
            if (height > 0 && width <= 0) {
                _scale = (float) height / srcHeight;
                width = (int) (srcWidth * _scale);
            }

            /* width - 将图像缩放到的宽度。 height - 将图像缩放到的高度。 hints - 指示用于图像重新取样的算法类型的标志。  */
            Image image = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);

            ImageFilter cropFilter = new CropImageFilter(0, 0, width, height);
            Image img = Toolkit.getDefaultToolkit().createImage(
                    new FilteredImageSource(image.getSource(), cropFilter));
            BufferedImage output = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics g = output.getGraphics();
            g.drawImage(img, 0, 0, width, height, null); // 绘制切割后的图
            g.dispose();
            if (!srcFile.delete()) {
                logger.error("删除源文件失败：" + srcFile.getPath());
            }
            //写出新的图片
            ImageIO.write(output, getFileExt(fullPath), new File(fullPath));
            return true;
        } catch (Exception ex) {
            logger.error("图片缩放失败：" + ex.getMessage());
            return false;
        }
    }

    /**
     * 图片缩放并载剪，以width为缩放依据
     *
     * @param srcPath 源路径
     * @param newPath 保存路径
     * @param width   宽度
     * @param height  高度
     * @return 是否成功
     */
    public static boolean zoomWithCut(String srcPath, String newPath, int width, int height) {
        if (srcPath == null || srcPath.trim().length() == 0) {
            return false;
        }
        File srcFile = new File(srcPath);
        return zoomWithCut(srcFile, newPath, width, height);
    }

    public static boolean zoomWithCut(File srcFile, String newPath, int width, int height) {
        try {
            //得到原图片
            BufferedImage srcImage = ImageIO.read(srcFile);
            return zoomWithCut(srcImage, newPath, width, height);
        } catch (Exception ex) {
            logger.error("图片缩放并裁剪失败：" + ex.getMessage());
            return false;
        }
    }

    public static boolean zoomWithCut(BufferedImage srcImage, String newPath, int width, int height) {
        if (width <= 0) {
            return false;
        }
        try {
            //获取图片高宽
            int srcWidth = srcImage.getWidth();
            int srcHeight = srcImage.getHeight();
            float _scale = (float) width / srcWidth;
            srcHeight = (int) (srcHeight * _scale);

            int filterH = Math.min(srcHeight, height);
            int filterY = 0;
            //原图比较高，从中间截取
            if (srcHeight > filterH) {
                filterY = (srcHeight - filterH) / 2;
            }

            /* width - 将图像缩放到的宽度。 height - 将图像缩放到的高度。 hints - 指示用于图像重新取样的算法类型的标志。  */
            Image image = srcImage.getScaledInstance(width, srcHeight, Image.SCALE_SMOOTH);

            ImageFilter cropFilter = new CropImageFilter(0, filterY, width, filterH);
            Image img = Toolkit.getDefaultToolkit().createImage(
                    new FilteredImageSource(image.getSource(), cropFilter));
            //ColorModel cm = ColorModel.getRGBdefault();
            //WritableRaster wr = cm.createCompatibleWritableRaster(width, height);
            //BufferedImage output = new BufferedImage(cm, wr, cm.isAlphaPremultiplied(), null);
            BufferedImage output = new BufferedImage(width, filterH, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = output.createGraphics();
            g.drawImage(img, 0, 0, width, filterH, null); // 绘制切割后的图
            g.dispose();
            File file = new File(newPath);
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            //写出新的图片
            ImageIO.write(output, getFileExt(newPath), file);
            return true;
        } catch (Exception ex) {
            logger.error("图片缩放并裁剪失败：" + ex.getMessage());
            return false;
        }
    }

    /**
     * 获取后缀
     *
     * @param str fileName
     * @return 返回文件后缀
     */
    private static String getFileExt(String str) {
        return str.substring(str.lastIndexOf(".") + 1).toLowerCase();
    }

    /**
     * 修改图片品质
     *
     * @param srcPath 图片原路径
     * @param newPath 图片保存路径
     * @param quality 0.1 - 1
     */
    public static boolean quality(String srcPath, String newPath, float quality) {

        if (srcPath == null || srcPath.length() < 5) {
            logger.error("srcPath:" + srcPath);
            return false;
        }
        if (newPath == null || newPath.length() < 5) {
            logger.error("newPath:" + newPath);
            return false;
        }
        String ext = getFileExt(srcPath);
        File newFile = new File(newPath);
        if (!newFile.getParentFile().exists()) {
            if (!newFile.getParentFile().mkdirs()) {
                System.out.println("创建目录失败：" + newFile.getPath());
            }
        }
        if (!ext.equalsIgnoreCase("jpg")) {
            logger.info("srcPath:" + srcPath);
            try {
                FileCopyUtils.copy(new File(srcPath), newFile);
            } catch (Exception ex) {
                logger.error("copy:" + ex.getMessage());
            }
            return true;
        }
        if (quality > 1) {
            quality = 1f;
        } else if (quality <= 0) {
            quality = 0.2f;
        }
        try {
            // 必须先指定 out值，才能调用write方法, ImageOutputStream可以通过任何
            // OutputStream构造
            // 指定写图片的方式为 jpg
            ImageWriter imgWriter = ImageIO.getImageWritersByFormatName(ext).next();
            ImageWriteParam imgWriteParams = imgWriter.getDefaultWriteParam();
            imgWriteParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            //这里指定图片品质，参数quality是取值0~1范围内，
            imgWriteParams.setCompressionQuality(quality);
            imgWriteParams.setProgressiveMode(ImageWriteParam.MODE_DEFAULT);

            BufferedImage src = ImageIO.read(new File(srcPath));
            ColorModel colorModel = ColorModel.getRGBdefault();
            // 指定压缩时使用的色彩模式
            imgWriteParams.setDestinationType(new ImageTypeSpecifier(
                    colorModel, colorModel.createCompatibleSampleModel(32, 32)));

            FileOutputStream out = new FileOutputStream(newFile);
            imgWriter.setOutput(ImageIO.createImageOutputStream(out));
            imgWriter.write(null, new IIOImage(src, null, null),
                    imgWriteParams);
            src.flush();
            out.flush();
            out.close();
            imgWriter.dispose();
        } catch (Exception e) {
            logger.error(e.getMessage());
            return false;
        }
        return true;
    }
    /**
     * 修改图片品质
     *
     * @param srcPath 图片原路径
     * @param quality 0.1 - 1
     */
    public static boolean quality(String srcPath, float quality) {
        return quality(srcPath, srcPath, quality);
    }
}